import { Injectable, Compiler, Injector, NgModuleRef, Component, NgModule, ViewContainerRef, ComponentRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import '@angular/compiler';


@Injectable({
  providedIn: 'root'
})
export class DynamicTemplateService {

  constructor(private compiler: Compiler,
    private injector: Injector,
    private moduleRef: NgModuleRef<any>) { }

  compilerTemplate(template: string,
    { vcRef, componentClass, components, styles }: {
      vcRef?: ViewContainerRef,
      componentClass?: Function,
      components?: any[],
      styles?: string[]
    } = {}): Promise<ComponentRef<any>> {

    const tplCmp = Component({ template, styles })(componentClass || class { });

    const tplModule = NgModule({
      imports: [CommonModule],
      declarations: Array.isArray(components) ? [tplCmp, ...components] : [tplCmp],
    })(class { });

    return this.compiler.compileModuleAndAllComponentsAsync(tplModule)
      .then(({ componentFactories }) => {
        const cf = componentFactories[0];
        const cmpRef = cf.create(this.injector, [], null, this.moduleRef);
        if (vcRef) {
          vcRef.insert(cmpRef.hostView);
        }
        return cmpRef;
      });
  }
}
